package com.xia.springboot.controller;


import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.xia.springboot.common.Result;
import com.xia.springboot.controller.dto.ItemQuantity;
import com.xia.springboot.controller.dto.ItemQuantityObject;
import com.xia.springboot.controller.dto.OrderDetail;
import com.xia.springboot.controller.dto.OrderDetail.QuantityItem;
import com.xia.springboot.entity.Item;
import com.xia.springboot.entity.Order;
import com.xia.springboot.entity.OrderItem;
import com.xia.springboot.entity.User;
import com.xia.springboot.mapper.ItemMapper;
import com.xia.springboot.mapper.OrderItemMapper;
import com.xia.springboot.mapper.OrderMapper;
import com.xia.springboot.mapper.UserMapper;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.SessionAttribute;

@RestController
@RequestMapping("/order")
public class OrderController {
    @Resource
    OrderMapper orderMapper;

    @Resource
    ItemMapper itemMapper;

    @Resource
    OrderItemMapper orderItemMapper;

    /**
     * 新建一个订单
     * @param itemQuantitySet
     * @return
     */
    @PostMapping
    public Result<?> save(@RequestBody Set<ItemQuantity> itemQuantitySet, @SessionAttribute("user") User user){
        Set<Integer> itemIdSet = itemQuantitySet.stream().map(itemQuantity -> itemQuantity.getItemId()).collect(Collectors.toSet());
        LambdaQueryWrapper<Item> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.in(Item::getId, itemIdSet);
        List<Item> itemList = itemMapper.selectList(queryWrapper);
        BigDecimal total = countItemTotalPrice(itemList, itemQuantitySet);

        Order order = new Order();
        // 获取商品名称
        order.setOrderName("");
        // 设置订单价格
        order.setPayPrice(total);
        // 设置邮费
        order.setPostFee(BigDecimal.ZERO);
        // 设置支付状态
        order.setState(2);
        // 设置用户的信息
        order.setUserId(user.getId());
        order.setUsername(user.getUsername());
        // 设置订单的预览图
        order.setOrderPicture("");
        //构建创建时间
        Date currDate = new Date();
        order.setCreateTime(currDate);
        // 保存订单
        orderMapper.insert(order);

        Integer orderId = order.getId();
        Map<Integer,Integer> itemQuantityMap = itemQuantitySet.stream().collect(Collectors.toMap(
            itemQuantity -> itemQuantity.getItemId(),
            itemQuantity -> itemQuantity.getQuantity(),
            (oldVal,newVal) -> oldVal
        ));

        for(Integer itemId : itemIdSet){
            int quantity = itemQuantityMap.get(itemId);
            OrderItem orderItem = new OrderItem(null, orderId, itemId, quantity);
            orderItemMapper.insert(orderItem);
        }

        return Result.success();
    }

    private BigDecimal countItemTotalPrice(List<Item> itemList, Set<ItemQuantity> itemQuantitySet) {
        Map<Integer,BigDecimal> itemIdPriceMap = itemList.stream().collect(
            Collectors.toMap(
                item -> item.getId(),
                item -> item.getPrice(),
                (oldVal,newVal) -> oldVal
            )
        );
        BigDecimal total = BigDecimal.ZERO;
        for(ItemQuantity quantity : itemQuantitySet){
            BigDecimal price = itemIdPriceMap.get(quantity.getItemId());
            BigDecimal value = price.multiply(BigDecimal.valueOf(quantity.getQuantity()));
            total.add(value);
        }
        return total;
    }

    //更新订单
    @PutMapping
    public Result<?> update(@RequestBody Order order){
        orderMapper.updateById(order);
        return Result.success();
    }

    //根据订单ID删除订单
    @DeleteMapping("/{id}")
    public Result<?> delete(@PathVariable Long id){
        orderMapper.deleteById(id);
        return Result.success();
    }

    //根据订单ID查询订单
    @GetMapping("/{id}")
    public Result<?> getById(@PathVariable Long id){
        Order order = orderMapper.selectById(id);

        LambdaQueryWrapper<OrderItem> orderItemWrapper = Wrappers.lambdaQuery();
        orderItemWrapper.eq(OrderItem::getOrderId, id);
        List<OrderItem> orderItemList = orderItemMapper.selectList(orderItemWrapper);

        Map<Integer,Integer> itemIdQuantityMap = orderItemList.stream().collect(Collectors.toMap(
            orderItem -> orderItem.getItemId(),
            orderItem -> orderItem.getQuantity(),
            (oldVal,newVal) -> oldVal
        ));

        Set<Integer> itemIdSet = orderItemList.stream().map(orderItem -> orderItem.getItemId()).collect(Collectors.toSet());

        LambdaQueryWrapper<Item> itemWrapper = Wrappers.lambdaQuery();
        itemWrapper.in(Item::getId, itemIdSet);
        List<Item> itemList = itemMapper.selectList(itemWrapper);

        List<ItemQuantityObject> objectList = Lists.newArrayList();
        for(Item item : itemList){
            int quantity = itemIdQuantityMap.get(item.getId());
            ItemQuantityObject quantityObject = new ItemQuantityObject(item, quantity);
            objectList.add(quantityObject);
        }

        Map<String,Object> result = new HashMap<>();
        result.put("order", order);
        result.put("itemList", objectList);

        return Result.success(result);
    }


    /**
     * 查询全部的订单消息
     * @param pageNum 当前的页数
     * @param pageSize 一页的大小
     * @param search 搜索的关键词
     * @return 结果集
     */
    @GetMapping
    public Result<?> findPage(@RequestParam(defaultValue = "1") Integer pageNum,
                              @RequestParam(defaultValue = "10") Integer pageSize,
                              @RequestParam(defaultValue = "") String search) {
        //新建分页对象
        Page<Order> page = new Page<>(pageNum, pageSize);
        //新建模糊查询对象,这里有个注意事项，你模糊项查询的对应项不能为null，为null就查不出来
        //LambdaQueryWrapper<User> queryWrapper = Wrappers.<User>lambdaQuery().like(User::getUsername, search);
        LambdaQueryWrapper<Order> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.orderByDesc(Order::getCreateTime);
        Page<Order> orderPage = orderMapper.selectPage(page, queryWrapper);
        List<Order> orderList = orderPage.getRecords();

        Page<OrderDetail> detailPage = new Page<>(pageNum, pageSize);
        List<OrderDetail> detailList = Lists.newLinkedList();
        for(Order order : orderList){
            Integer orderId = order.getId();
            LambdaQueryWrapper<OrderItem> itemWrapper = Wrappers.lambdaQuery();
            itemWrapper.eq(OrderItem::getOrderId, orderId);
            List<OrderItem> orderItemList = orderItemMapper.selectList(itemWrapper);
            List<Item> itemList = itemList(orderItemList);
            List<QuantityItem> quantityItemList = mapOrderItem(orderItemList, itemList);
            OrderDetail orderDetail = new OrderDetail(order, quantityItemList);
            detailList.add(orderDetail);
        }
        detailPage.setRecords(detailList);
        return Result.success(detailPage);
    }

    private List<QuantityItem> mapOrderItem(List<OrderItem> orderItemList, List<Item> itemList) {
        Map<Integer,Integer> itemIdQuantityMap = orderItemList.stream().collect(
            Collectors.toMap(
                orderItem -> orderItem.getItemId(),
                orderItem -> orderItem.getQuantity(),
                (oldVal,newVal) -> oldVal
            )
        );

        List<QuantityItem> quantityItemList = Lists.newLinkedList();
        for(Item item : itemList){
            quantityItemList.add(new QuantityItem(item, itemIdQuantityMap.get(item.getId())));
        }
        return quantityItemList;
    }

    private List<Item> itemList(List<OrderItem> orderItemList) {
        if(orderItemList.size() == 0){
            return Lists.newLinkedList();
        }
        Set<Integer> itemIdSet = orderItemList.stream().map(orderItem -> orderItem.getItemId()).collect(Collectors.toSet());

        return itemMapper.selectBatchIds(itemIdSet);
    }

}
